﻿using UnityEditor;
using UnityEngine;
using System.Collections;
using System;
using System.IO;

class ExportProject
{
    static string[] BuildScenes
    {
        get
        {
            // Login,City,World都打成AssetBundle,这边只需要导出GameMain.unity
            return new string[] { "Assets/Scenes/GameMain.unity" };
        }
    }

    static void BuildSetting(BuildTarget target)
    {
        BuildTargetGroup group = BuildPipeline.GetBuildTargetGroup(target);

        CommandHelper.InitPropertyFromCommandline();

        PlayerSettings.applicationIdentifier = ConfigHelper.BundleId;
        PlayerSettings.bundleVersion = EditorConfig.BundleVersion;

        switch (target)
        {
            case BuildTarget.iOS:
                PlayerSettings.productName = ConfigHelper.GameName;
                PlayerSettings.iOS.buildNumber = EditorConfig.BuildNumber;
                break;

            case BuildTarget.Android:
                PlayerSettings.productName = CommandHelper.ProductName;
                PlayerSettings.Android.bundleVersionCode = EditorConfig.BundleVersionCode;

                // 这里暂时加个判断, Windows就不更新了
                if (Application.platform != RuntimePlatform.WindowsEditor)
                    // 更新安卓EditorPrefsSettings
                    SettingAndroidEditorPrefs();
                break;
        }

        PlayerSettings.SetScriptingDefineSymbolsForGroup(group, CommandHelper.DefineSymbols);

        if (!string.IsNullOrEmpty(CommandHelper.IconName))
        {
            Texture2D[] icons = PlayerSettings.GetIconsForTargetGroup(group);
            var texture = AssetDatabase.LoadAssetAtPath(string.Format("Assets/App/{0}.png", CommandHelper.IconName), typeof(Texture2D)) as Texture2D;
            if (texture != null)
            {
                for (int i = 0; i < icons.Length; i++)
                {
                    icons[i] = texture;
                }
                PlayerSettings.SetIconsForTargetGroup(group, icons);
            }
        }
    }

    // 更新安卓EditorPrefsSettings
    public static void SettingAndroidEditorPrefs()
    {
        // 设置SDK路径
        if (string.IsNullOrEmpty(EditorPrefs.GetString("AndroidSdkRoot")))
            SettingEditorPrefsPath("AndroidSdkRoot", "ANDROID_SDK_ROOT", "", "/Library/Android/SDK");

        // 设置JDK路径
        if (string.IsNullOrEmpty(EditorPrefs.GetString("JdkPath")))
            SettingEditorPrefsPath("JdkPath", "ANDROID_JDK_ROOT", "", "/Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home");

        // 设置NDK路径
        if (string.IsNullOrEmpty(EditorPrefs.GetString("AndroidNdkRoot")))
            SettingEditorPrefsPath("AndroidNdkRoot", "ANDROID_NDK_ROOT", "", "/Library/Android/android-ndk-r10e");
    }

    /// <summary>
    /// 设置EditorPrefs路径相关配置
    /// </summary>
    /// <param name="key">EditorPrefs key</param>
    /// <param name="environmentKey">系统环境变量</param>
    /// <param name="defaultWindowsPath">默认Windows路径</param>
    /// <param name="defaultMacOSPath">默认Mac路径</param>
    private static void SettingEditorPrefsPath(string key, string environmentKey, string defaultWindowsPath, string defaultMacOSPath)
    {
        // 取系统环境变量
        string environmentPath = Environment.GetEnvironmentVariable(environmentKey);
        if (string.IsNullOrEmpty(environmentPath))
        {
            // 取不到, 把默认路径设置到系统环境变量里
            string defaultPath = Application.platform == RuntimePlatform.WindowsEditor ? defaultWindowsPath : defaultMacOSPath;
            Environment.SetEnvironmentVariable(environmentKey, defaultPath);
            environmentPath = defaultPath;
        }

        // 路径不存在
        if (!Directory.Exists(environmentPath))
        {
            Debug.Log("Environment Path Error");
            return;
        }

        // 设置EditorPrefs
        EditorPrefs.SetString(key, environmentPath);
    }

    static void BuildSetScriptingBackend(BuildTarget target, int flag)
    {
        BuildTargetGroup group = BuildPipeline.GetBuildTargetGroup(target);

        ScriptingImplementation backend = ScriptingImplementation.IL2CPP;
        int architecture = -1;

        switch (flag)
        {
            case 1:     // IL2CPP ArmV7
                backend = ScriptingImplementation.IL2CPP;
                architecture = 0;
                break;

            case 2:     // IL2CPP Arm64
                backend = ScriptingImplementation.IL2CPP;
                architecture = 1;
                break;

            case 3:     // IL2CPP Universal
                backend = ScriptingImplementation.IL2CPP;
                architecture = 2;
                break;

            default:    // other Use Mono2.x
                backend = ScriptingImplementation.Mono2x;
                break;
        }
        //如果是UWA，强制使用mono2x
        if (CommandHelper.DefineSymbols.Contains("UWA"))
        {
            backend = ScriptingImplementation.Mono2x;
        }

        // 设置编译环境IL2CPP/Mono2x
        PlayerSettings.SetScriptingBackend(group, backend);
        switch (target)
        {
            case BuildTarget.iOS:
                if (architecture != -1)
                {
                    // IOS设置 ArmV7/Arm64/Universal
                    PlayerSettings.SetArchitecture(group, architecture);
                }
                break;
        }
    }

    static void SaveAndroidConfig()
    {
        // 版本号
        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        sb.AppendFormat("GAME_NAME={0}\n", ConfigHelper.GameName);
        sb.AppendFormat("VERSION_NAME={0}\n", EditorConfig.BundleVersion);
        sb.AppendFormat("VERSION_CODE={0}\n", EditorConfig.BundleVersionCode);
        sb.AppendFormat("BUNDLE_IDENTIFIER={0}\n", ConfigHelper.BundleId);
        sb.AppendFormat("IS_DEVELOPER={0}\n", ConfigHelper.IsDeveloper);

        FileHelper.SaveTextToFile(sb.ToString(), string.Format("{0}/{1}/version.properties", CommandHelper.OutputPath, CommandHelper.ProductName));
    }

    public static void BuildInner(BuildTarget target)
    {
        Debug.Log("Export Project BuildInner 1");
#if UNITY_IOS && UWA
		SLua.LuaCodeGen.GenerateAll();
#endif
        Debug.Log("Export Project BuildInner 2");
#if REPORTER
		PrepareReporter ();
#endif
        Debug.Log("Export Project BuildInner 3");
        // 检查更新, 对应打包参数epicu里的c参数
        if (ConfigHelper.CheckUpdate)
        {
            if (ExportVersion.CheckVersionAndRename())
            {
                // 累加版本, Version也是py传过来的
                string version = ConfigHelper.Version;
                version = EditorHelper.NextVersion(version, EditorHelper.VersionCodeFlag.MIDDLE);
                ConfigHelper.Version = version;
            }

            // 导出当前版本的MD5
            ExportVersion.InitVersion();
        }

        Debug.Log("Export Project BuildInner 4");
        //  修改Assets/Config/config.asset里的PackageCode，打包编码，每次打包时生成，区分每一个包，暂时用打包时间
        ConfigHelper.UpdatePackageCode();

        // 计算AB需要的磁盘空间, 存到MinNeedDiskSize
        ConfigHelper.CalcNeedDiskSize();

        Debug.Log("Export Project BuildInner 5");
        // 设置编译参数
        BuildSetScriptingBackend(target, CommandHelper.Arch);

        // 导出路径 CommandHelper.OutputPath = “Project”
        string path = CommandHelper.OutputPath;

        // 编译选项
        BuildOptions options = BuildOptions.None;

        // CommandHelper.IsDevelopment, py传过来的d参数
        if (CommandHelper.IsDevelopment)
        {
            options |= BuildOptions.Development;
            options |= BuildOptions.AllowDebugging;
            options |= BuildOptions.ConnectWithProfiler;
        }

        switch (target)
        {
            case BuildTarget.iOS:
                // 禁用自动签名
                PlayerSettings.iOS.appleEnableAutomaticSigning = false;

                if (ConfigHelper.Release != ReleaseType.RELEASE)
                {
                    // 非正式版,勾选Symlink Unity Libraries,加速编译
                    // 生成iOS Xcode项目时的Symlink运行时库。（更快的迭代时间）。
                    // 这个选项方便调试，减少build时间，正式打包，不能勾选
                    // 可能是IOS build工程目录下的ModuleCache
                    EditorUserBuildSettings.symlinkLibraries = true;
                }

                // 使用Export Project方式导出, 导出 Xcode (iOS) or Eclipse (Android) projects, 不直接导出apk
                // 有这句打出来的xcode工程才能在已有的工程上追加内容
                options |= BuildOptions.AcceptExternalModificationsToPlayer;

                // CommandHelper.ProductName = dk_ios/oe_ios
                path = string.Format("{0}/{1}", CommandHelper.OutputPath, CommandHelper.ProductName);
                break;

            case BuildTarget.Android:
                // 使用ETC
                EditorUserBuildSettings.androidBuildSubtarget = MobileTextureSubtarget.ETC;

                // 目前的方案, 要用ADT导出, 对应的地方是Build Setting, 选完Android平台后右边的Build System
                // Internal（Default）：Unity内置，仅需Android SDK支持。不能导出工程，适用于仅适用Unity开发的工程。
                // Gradle（New）：使用Gradle进行构建，需要Android SDK与Gradle支持。可以导出Android Studio工程，选这个才能勾选下面的Export Project，适用于Unity与Android交互的项目。
                // ADT（Legacy）：使用ADT进行构建，需要Android SDK与ADT支持。可以导出Eclipse项目，现逐渐被弃用（Unity2017.3中已经没该选项了）。
                EditorUserBuildSettings.androidBuildSystem = AndroidBuildSystem.ADT;

                // 保存参数, 一些安卓需要的参数, 保存到oe_android/version.properties里
                SaveAndroidConfig();

                // 使用Export Project方式导出, 导出 Xcode (iOS) or Eclipse (Android) projects, 不直接导出apk
                // 有这句打出来的xcode工程才能在已有的工程上追加内容
                options |= BuildOptions.AcceptExternalModificationsToPlayer;
                break;

            default:
                // 其它,认为是Standalone
                // 先只用Windows x86_64
                EditorUserBuildSettings.selectedStandaloneTarget = BuildTarget.StandaloneWindows64;

                // 导出路径
                path = string.Format("{0}/{1}.exe", CommandHelper.OutputPath, CommandHelper.ProductName);
                break;
        }

        Debug.Log("Export Project BuildInner 6");
        // BuildScenes : Login, City, World都打成AssetBundle, 这边只导出GameMain.unity
        BuildPipeline.BuildPlayer(BuildScenes, path, target, options);
        Debug.Log("Export Project BuildInner 7");
    }

    // 保存当前平台类型
    static void SavePlatform()
    {
        BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
        BuildTargetGroup group = BuildPipeline.GetBuildTargetGroup(target);
        PlayerSettings.SetScriptingDefineSymbolsForGroup(group, CommandHelper.DefineSymbols);

        System.Text.StringBuilder sb = new System.Text.StringBuilder();
        sb.AppendFormat("{0}", (int)EditorConfig.BUILD_TARGET);

        FileHelper.SaveTextToFile(sb.ToString(), CommandHelper.OutputPath);
    }

    // 导出工程
    static void Export()
    {
        BuildTarget target = EditorUserBuildSettings.activeBuildTarget;
        BuildSetting(target);

        // CommandHelper.ExportType 是py传过来的self._exportType, 对应epicu里的ep, 测试包、正测包、提审包都有ep
        // self._exportType默认 = 0, self.ExportType.AssetBundle/self.ExportType.Project
        EditorConfig.ExportType et = CommandHelper.ExportType;
        Debug.LogFormat("Export Type: {0}", et);

        // 导出AB
        if ((et & EditorConfig.ExportType.ASSET_BUNDLE) != 0)
        {
            Debug.Log("Export Project Export 1");
            // 导出AssetBundle
            ExportVersion.RemoveLuaPatchs();
            Debug.Log("Export Project Export 2");
            ExportAssetBundle.BuildInner();
        }

        if ((et & EditorConfig.ExportType.PROJECT) != 0)
        {
            Debug.Log("Export Project Export 3");
            // 导出工程
            BuildInner(target);
            Debug.Log("Export Project Export 4");
        }
    }

    public static void ExportAB()
    {
        ExportVersion.RemoveLuaPatchs();
        ExportAssetBundle.BuildInner();
    }
}